import {
	CustomViewActionType,
	ICustomViewAbility,
	ICustomViewController,
	ICustomViewStore,
	IParam,
	IViewActionResult,
	ICustomViewControllerParams,
	ICustomViewModel,
	IViewEngine,
	IViewEngineParams,
	IDECtrlAbility,
} from '@/core/interface';
import { deepCopy, LogUtil } from '@/core/utils';
import { DEViewController } from './de-view-controller';

/**
 * 自定义视图控制器
 *
 * @export
 * @class CustomViewController
 * @extends {DEViewController<T, S, A>}
 * @implements {ICustomViewController}
 */
export class CustomViewController
	extends DEViewController<
		CustomViewActionType,
		ICustomViewStore,
		ICustomViewAbility
	>
	implements ICustomViewController<ICustomViewStore, ICustomViewAbility>
{
	/**
	 * 自定义视图模型
	 *
	 * @type {ICustomViewModel}
	 * @memberof CustomViewController
	 */
	declare readonly model: ICustomViewModel;

	/**
	 * 部件引擎集合
	 *
	 * @private
	 * @type {IParam[]}
	 * @memberof CustomViewController
	 */
	private ctrlEngineArray: IParam[] = [];

	/**
	 * Creates an instance of CustomViewController.
	 * @param {ICustomViewControllerParams<ICustomViewStore, ICustomViewAbility>} params
	 * @memberof CustomViewController
	 */
	constructor(
		params: ICustomViewControllerParams<ICustomViewStore, ICustomViewAbility>
	) {
		super(params);
		this.initCtrlEngineArray();
	}

	/**
	 * 初始化引擎集合
	 *
	 * @private
	 * @memberof CustomViewController
	 */
	private initCtrlEngineArray() {
		const { engineArray } = this.model;
		this.ctrlEngineArray = [];
		engineArray.forEach((engine: IViewEngine) => {
			const result = this.handleViewEngineParams(engine);
			if (result) {
				this.ctrlEngineArray.push(result);
			}
		});
	}

	/**
	 * 视图加载
	 *
	 * @param {IParam} [opts={}]
	 * @memberof CustomViewController
	 */
	public viewMounted(opts: IParam = {}) {
		super.viewMounted(opts);
		if (this.model.useDefaultLayout) {
			if (!this.isLoadDefault) {
				this.isLoadDefault = true;
				return;
			}
			this.load(opts);
		} else {
			this.initLayout().then(() => {
				if (!this.isLoadDefault) {
					this.isLoadDefault = true;
					return;
				}
				this.load(opts);
			});
		}
	}

	/**
	 * 视图加载
	 *
	 * @param {IParam} [args]
	 * @return {*}  {Promise<IViewActionResult>}
	 * @memberof CustomViewController
	 */
	public load(args?: IParam): Promise<IViewActionResult> {
		const tempViewParams = deepCopy(this.store.viewParams);
		Object.assign(tempViewParams, args);
		if (this.ctrlEngineArray.length > 0) {
			// 处理搜索部件加载并搜索（参数可指定触发部件）
			for (let engine of this.ctrlEngineArray) {
				if (
					engine.triggerCtrlName &&
					Object.is(engine.triggerCtrlName, 'VIEW') &&
					engine.triggerType &&
					Object.is(engine.triggerType, 'CtrlLoadAndSearch')
				) {
					const ctrl: any = this.getSubAbility<IDECtrlAbility>(
						engine.targetCtrlName
					);
					if (ctrl && ctrl['loadDraft']) {
						return ctrl['loadDraft'](tempViewParams);
					}
				}
			}
			// 处理部件加载（参数可指定触发部件）无指定触发部件时由容器触发
			for (let engine of this.ctrlEngineArray) {
				if (
					engine.triggerType &&
					Object.is(engine.triggerType, 'CtrlLoad') &&
					!engine.triggerCtrlName
				) {
					const ctrl: any = this.getSubAbility<IDECtrlAbility>(
						engine.targetCtrlName
					);
					if (ctrl) {
						let action = 'load';
						if (
							engine.targetCtrlName &&
							Object.is(engine.targetCtrlName, 'form')
						) {
							if (
								!this.model.entityCodeName ||
								(this.model.entityCodeName &&
									!this.store.context[this.model.entityCodeName.toLowerCase()])
							) {
								action = 'loadDraft';
							}
						}
						if (ctrl[action]) {
							return ctrl[action](tempViewParams);
						}
					}
				}
			}
		}
		return Promise.reject({
			ok: false,
			data: null,
			rowData: { status: 500 },
		});
	}

	/**
	 * 刷新视图
	 *
	 * @param {(IParam | undefined)} [args]
	 * @return {*}  {Promise<boolean>}
	 * @memberof CustomViewController
	 */
	public async refresh(args?: IParam | undefined): Promise<boolean> {
		return (await this.load(args)).ok;
	}

	/**
	 * 处理视图引擎参数
	 *
	 * @private
	 * @param {IParam} engine
	 * @return {*}
	 * @memberof CustomViewController
	 */
	private handleViewEngineParams(engine: IViewEngine) {
		switch (engine.engineType) {
			case 'CtrlLoadTrigger':
				return this.handleCtrlLoad(engine.engineParams);
			case 'CtrlLoad':
				return this.handleCtrlLoad(engine.engineParams);
			case 'CtrlLoadAndSearch':
				return this.CtrlLoadAndSearch(engine.engineParams);
			default:
				LogUtil.warn(`${engine.engineType}暂未支持`);
				break;
		}
	}

	/**
	 * 处理搜索部件加载并搜索（参数可指定触发部件）
	 *
	 * @private
	 * @param {IParam} engineParams
	 * @return {*}
	 * @memberof CustomViewController
	 */
	private CtrlLoadAndSearch(engineParams: IViewEngineParams[]) {
		if (!engineParams || engineParams.length < 1) {
			return null;
		}
		const targetCtrl = engineParams.find((item: any) => {
			return item.name === 'CTRL' && item.paramType === 'CTRL';
		});
		return {
			triggerCtrlName: 'VIEW',
			triggerType: 'CtrlLoadAndSearch',
			targetCtrlName: targetCtrl?.ctrlName,
		};
	}

	/**
	 * 处理部件加载（参数可指定触发部件）
	 *
	 * @private
	 * @param {IParam} engineParams
	 * @return {*}
	 * @memberof CustomViewController
	 */
	private handleCtrlLoad(engineParams: IViewEngineParams[]) {
		if (!engineParams || engineParams.length < 1) {
			return null;
		}
		const triggerCtrl = engineParams.find((item: any) => {
			return item.name === 'TRIGGER' && item.paramType === 'CTRL';
		});
		const targetCtrl = engineParams.find((item: any) => {
			return item.name === 'CTRL' && item.paramType === 'CTRL';
		});
		return {
			triggerCtrlName: triggerCtrl?.ctrlName,
			triggerType: 'CtrlLoad',
			targetCtrlName: targetCtrl?.ctrlName,
		};
	}

	/**
	 * 处理部件行为
	 *
	 * @param {string} name
	 * @param {string} action
	 * @param {IParam[]} data
	 * @memberof CustomViewController
	 */
	public handleCtrlAction(name: string, action: string, data: IParam[]): void {
		super.handleCtrlAction(name, action, data);
		if (
			Object.is(action, 'load') ||
			Object.is(action, 'search') ||
			Object.is(action, 'selectionChange') ||
			Object.is(action, 'dataActive')
		) {
			for (let engine of this.ctrlEngineArray) {
				if (
					engine.triggerCtrlName &&
					Object.is(engine.triggerCtrlName, name) &&
					engine.triggerType &&
					Object.is(engine.triggerType, 'CtrlLoad')
				) {
					const ctrl: any = this.getSubAbility<IDECtrlAbility>(
						engine.targetCtrlName
					);
					if (ctrl && ctrl['load']) {
						ctrl['load'](deepCopy(data[0]));
					}
				}
			}
		}
	}
}
